﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WorkStation.Frameworks.Core.Extensions;

namespace WorkStation.Frameworks.EasyBus.MessageQueue
{
    /// <summary>
    /// 消息队列地址翻译接口
    /// </summary>
    public interface IQueueAddressTranslator
    {
        /// <summary>
        /// 前缀
        /// </summary>
        string Prefix { get; }

        /// <summary>
        /// 终结点类型
        /// </summary>
        Type EndpointType { get; }

        /// <summary>
        /// 建立终结点
        /// </summary>
        /// <param name="queueAddress">队列地址</param>
        /// <returns></returns>
        IEndpoint CreateEndpoint(string queueAddress);

        /// <summary>
        /// 从终结点转到地址字串
        /// </summary>
        /// <param name="endpoint"></param>
        /// <returns></returns>
        string EndpointToString(IEndpoint endpoint);
    }

    public abstract class QueueAddressTranslatorBase : IQueueAddressTranslator
    {
        protected static readonly string IS_SYNC_NAME_KEY = "IsSynchronization";

        public List<string> ParameterNames { get; set; }

        public abstract string Prefix { get; }
        public abstract Type EndpointType { get; protected set; }

        public QueueAddressTranslatorBase() 
        {
            this.ParameterNames = new List<string>() 
            {
                IS_SYNC_NAME_KEY
            };
        }

        public string EndpointToString(IEndpoint endpoint) 
        {
            if (!this.CanEndpointToString(endpoint)) { return null; }

            StringBuilder builder = new StringBuilder("{0}:".Fmt(this.Prefix));

            Type type = endpoint.GetType();

            var properties = type.GetProperties();

            foreach (string parameterName in this.ParameterNames) 
            {
                builder.Append("{0}={1};".Fmt(parameterName, properties.FirstOrDefault(v => v.Name.Equals(parameterName)).GetValue(endpoint, null).ToString()));
            }

            return builder.Remove(builder.Length - 1, 1).ToString();
        }

        public IEndpoint CreateEndpoint(string queueAddress) 
        {
            if (queueAddress.IsNullOrEmpty()) 
            {
                throw new ArgumentNullException("queueAddress");
            }

            Dictionary<string, string> parameters = null;

            if (this.CanTranslate(queueAddress))
            {
                try
                {
                    parameters = queueAddress.Replace("{0}:".Fmt(this.Prefix), "")
                                             .Split(';')
                                             .Select(v => new KeyValuePair<string, string>(v.Split('=')[0], v.Split('=')[1]))
                                             .ToDictionary(key => key.Key, value => value.Value);
                }
                catch (Exception ce)
                {
                    throw new EasyBusException(string.Format("设置格式异常，设置字符串【{0}】", queueAddress));
                }

                this.CheckParameters(parameters);

                IEndpoint endpoint = this.TranslateToEndpointCore(parameters);

                endpoint.IsSynchronization = Convert.ToBoolean(parameters[IS_SYNC_NAME_KEY].ToLower());

                return endpoint;
            }
            else 
            {
                return null;
            }
        }

        protected abstract IEndpoint TranslateToEndpointCore(Dictionary<string, string> parameters);

        protected bool CanEndpointToString(IEndpoint endpoint) 
        {
            if (endpoint.GetType() == this.EndpointType)
            {
                return true;
            }
            else 
            {
                return false;
            }
        }

        protected virtual void CheckParameters(Dictionary<string, string> parameters) 
        {
            if (this.ParameterNames == null) 
            {
                throw new EasyBusException("在实现翻译器时需要填入字符串参数名称");
            }

            StringBuilder builder = new StringBuilder(string.Empty);

            foreach (string parameterName in this.ParameterNames) 
            {
                if (!parameters.ContainsKey(parameterName)) 
                {
                    builder.Append("地址字符串缺少参数：【{0}】{1}".Fmt(parameterName, Environment.NewLine));
                }
            }

            string res = builder.ToString();

            if (res != string.Empty) 
            {
                throw new EasyBusException(res.ToString());
            }
        }

        protected virtual bool CanTranslate(string queueAddress) 
        {
            return queueAddress.StartsWith(this.Prefix);
        }
    }
}
